/**
 * @file CMMsgTaskManager.h
 * @brief 消息通信管理接口，基于 interface 实现，并在此处注册
 */

#ifndef JKLIBS_CMMSGTASKMANAGER_H
#define JKLIBS_CMMSGTASKMANAGER_H

#include <list>
#include <map>
#include <vector>

#include "CMLock.h"
#include "CMMsgTaskInterface.h"

/**
 * 本功能用于线程间的消息发送
 * 如果你有多个线程，线程之间异步操作，需要将一个消息发送到另一个线程去处理，这是一个可用的异步方案
 * 在你的功能类中继承  CMMsgTaskInterface ，然后实现 handler 函数
 * 然后注册进此类，即可。
 * 如果你要发送消息，则调用 Send 函数
 * name - caller1
 *      - caller2 - msg1
 *               - msg2
 * 一个名称下可以有多个注册监听者，往这些监听者发送的消息，均会收到
 */

class CMMsgTaskInfo
{
  public:
    CMMsgTaskInfo() {}

    class CMMsgCmdList
    {
      public:
        int   m_cmd;
        char *m_args;
        void *m_data;
    };

    std::string                     m_name;
    std::vector<CMMsgCmdList>       m_cmdList;
    std::list<CMMsgTaskInterface *> m_callers;
};

class CMMsgTaskManager
{
  public:
    CMMsgTaskManager() { m_exit = false; }

    int  Init();
    void Deinit();
    void Clear();

    /**
     * 注册，调用者将监听者与name匹配，一个name可以匹配多个调用者
     * @param name
     * @param caller
     * @return
     *   @retval 返回当前名称的监听者数量
     */
    int Register(const char *name, CMMsgTaskInterface *caller);

    /**
     * 解除绑定，注意是解除当前名称下的监听者
     * 勿理解为解除 name
     * @param name
     * @param caller
     * @return
     *   @retval 返回当前名称下有多少监听者
     */
    int Unregister(const char *name, CMMsgTaskInterface *caller);

    /**
     * 发送消息事件， 消息可自由协商，消息为异步发送，所以并非立即收到，间隔最短
     * 50ms
     * @param name 发送给谁
     * @param cmd 消息的命令
     * @param args 消息的参数
     * @param data 消息的数据结构体
     * @return
     *  @retval -1 参数错误
     *  @retval -2 本名称没有消息监听者
     *  @retval 0 发送成功
     */
    int Send(const char *name, int cmd, char *args, void *data);

  protected:
    friend void *msg_task_manager_run_thread(void *args);

    int AddNew(const char *name, CMMsgTaskInterface *caller);
    int AddMsg(CMMsgTaskInfo *msgTaskInfo, int cmd, char *args, void *data);

  private:
    std::map<std::string, CMMsgTaskInfo *> m_tasks;
    CMLock                                 m_lock;
    bool                                   m_exit;
};

#endif // JKLIBS_CMMSGTASKMANAGER_H
